<!-- 组件中盒子的阴影由 box-shadow 决定 -->

<script setup lang="ts">
import {NList, NListItem, NCheckbox, NButton, NScrollbar, NTabs, NTabPane, NRadioGroup, NRadioButton} from 'naive-ui'
import StnCollapsePopBtn from "../StnCollapsePopBtn"
import '../StnCollapsePopBtn/StnCollapsePopBtn.scss'
import {StPopover, StIconIconify} from 'st-common-ui-vue3'
import 'st-common-ui-vue3/es/components/StPopover/StPopover.css'
import 'st-common-ui-vue3/es/components/StIconIconify/StIconIconify.css'
import Settings from '@iconify-icons/tabler/settings'
import {inject, Ref, ref, watchEffect} from "vue"
import type {StnDataTableColumns} from '@/components/StnTable'
import {VueDraggable} from 'vue-draggable-plus'
import ArrowsMoveVertical from '@iconify-icons/tabler/arrows-move-vertical'
import {elSizeUtil} from 'st-common-ui-utils'

/**
 * 组件配置选项
 */
defineOptions({
  name: 'StnTableColSetting',
})

/**
 * 组件参数
 */
withDefaults(
  defineProps<{
    // 按钮是否折叠收缩展示
    btnCollapse?: boolean;
    // 按钮文本
    btnText?: string;
    // 列设置弹框层级
    colSettingPopZIndex?: number;
    // 列设置弹框最大宽度
    colSettingPopMaxWidth?: string | number;
    // 列设置列表最大高度
    listMaxHeight?: string | number;
    // 列展示 tab 名称
    colShowTabName?: string;
    // 列固定 tab 名称
    colFixTabName?: string;
    // 列对齐 tab 名称
    colAlignTabName?: string;
    // 全选按钮文本
    allText?: string;
    // 重置按钮文本
    resetText?: string;
    // 左对齐文本
    leftText?: string;
    // 居中对齐文本
    centerText?: string;
    // 右对齐文本
    rightText?: string;
  }>(),
  {
    btnCollapse: false,
    btnText: '列设置',
    colSettingPopZIndex: 4,
    colSettingPopMaxWidth: '200px',
    listMaxHeight: '300px',
    colShowTabName: '列展示',
    colFixTabName: '列固定',
    colAlignTabName: '列对齐',
    allText: '全选',
    resetText: '重置',
    leftText: '左',
    centerText: '居中',
    rightText: '右',
  }
)

// 表格列配置组件的引用对象
const columnsSettingRef = ref<HTMLDivElement>()

// 表格的列配置
const columns = inject('columns') as Ref<StnDataTableColumns>

// 需要展示的表格列
const columnsShowed = inject('columnsShowed') as Ref<StnDataTableColumns>
// 需要展示的表格列是否为部分表格列
const isColumnsShowedIndeterminate = ref(false)
// 需要展示的表格列是否为全部表格列
const isColumnsShowedAll = ref(false)
// 是否只有部分列固定
const isIndeterminateColumnsFixed = ref(false)
// 是否所有列都固定
const isAllColumnsFixed = ref(false)
/**
 * 表格列发生更新的处理函数
 */
const columnsUpdateHandler = (columns: StnDataTableColumns) => {
  // 记录需要展示的表格列的个数
  let columnsShowedCount = 0
  // 可以选择是否固定的列的总个数
  let columnsFixedSum = 0
  // 固定列的个数
  let columnsFixedCnt = 0
  // 更新需要展示的表格列
  columnsShowed.value = columns.filter(column => {
    if (column.checked) columnsShowedCount++
    if (column.originFixed) columnsFixedSum++
    if (column.fixed) columnsFixedCnt++
    return column.checked
  })
  // 判断需要展示的表格列是否为部分表格列
  isColumnsShowedIndeterminate.value = columns.length > 0 && columnsShowedCount > 0 && columnsShowedCount < columns.length
  // 判断需要展示的表格列是否为全部表格列
  isColumnsShowedAll.value = columns.length > 0 && columnsShowedCount === columns.length
  // 判断是否只有部分列固定
  isIndeterminateColumnsFixed.value = columns.length > 0 && columnsFixedCnt > 0 && columnsFixedCnt < columnsFixedSum
  // 判断是否所有表格列都固定
  isAllColumnsFixed.value = columns.length > 0 && columnsFixedCnt === columnsFixedSum
}

// 监听 columns 变化
watchEffect(() => {
  columnsUpdateHandler(columns.value)
})

/**
 * 更新表格列展示的全选复选框是否选中的处理函数
 *
 * @param checked 表格列展示的全选复选框是否选中
 */
const updateColumnsShowedAllHandler = (checked: boolean) => {
  columns.value.forEach(column => {
    if (!column.disableChecked) {
      column.checked = checked
    }
  })
}

/**
 * 更新表格列固定的全选复选框是否选中的处理函数
 *
 * @param {boolean} checked 表格列固定的全选复选框是否选中
 */
const updateColumnsFixedAllHandler = (checked: boolean) => {
  columns.value.forEach(column => {
    // 只有设置了 fixed 属性的列才能被全选按钮改变固定状态
    if (column.originFixed) {
      column.fixed = (checked ? column.originFixed : false) as 'left' | 'right' | undefined
    }
  })
}

/**
 * 重置表格列的展示状态
 */
const resetColumnsShowedHandler = () => {
  columns.value = columns.value.sort((a, b) => (a.sort as number) - (b.sort as number))
  columns.value.forEach((column) => {
    column.checked = column.originChecked
  })
}

/**
 * 重置表格列的固定
 */
const resetColumnsFixedHandler = () => {
  columns.value.forEach((column) => {
    column.fixed = column.originFixed
  })
}

/**
 * 重置表格列的内容对其方式
 */
const resetColumnsAlignHandler = () => {
  columns.value.forEach((column) => {
    column.align = column.originAlign
  })
}
</script>

<template>
  <div ref="columnsSettingRef" class="stn-table-columns-setting">
    <StPopover :is-vertical="true" :sub-cont-z-index="colSettingPopZIndex">
      <template #default>
        <div class="stn-table-columns-setting__btn">
          <slot name="btn">
            <StnCollapsePopBtn block :is-collapse="btnCollapse" :btn-text="btnText">
              <template #icon>
                <slot name="btn-icon">
                  <st-icon-iconify :icon="Settings"/>
                </slot>
              </template>
            </StnCollapsePopBtn>
          </slot>
        </div>
      </template>
      <template #subContent>
        <div
          class="stn-table-columns-setting__columns-setting box-bg box-shadow"
          :style="{
            maxWidth: elSizeUtil.elSizePreHandler(colSettingPopMaxWidth),
            margin: '0.5rem 0'
          }"
        >
          <n-tabs animated>
            <n-tab-pane :name="colShowTabName">
              <n-list hoverable clickable>
                <n-list-item>
                  <div class="stn-table-columns-setting__columns-setting__all-reset">
                    <n-checkbox
                      size="small"
                      v-model:checked="isColumnsShowedAll"
                      :indeterminate="isColumnsShowedIndeterminate"
                      @update:checked="updateColumnsShowedAllHandler"
                    >
                      <span style="white-space: nowrap">{{ allText }}</span>
                    </n-checkbox>
                    <n-button text size="small" @click="resetColumnsShowedHandler">{{ resetText }}</n-button>
                  </div>
                </n-list-item>
                <n-scrollbar
                  class="stn-table-columns-setting__columns-setting__list"
                  :style="{maxHeight: elSizeUtil.elSizePreHandler(listMaxHeight)}"
                  trigger="none"
                >
                  <VueDraggable
                    v-model="columns"
                    handle=".stn-table-columns-setting__columns-setting__item-handler"
                  >
                    <div
                      v-for="column in columns"
                      :key="column.title"
                      class="stn-table-columns-setting__columns-setting__item"
                    >
                      <n-list-item>
                        <div class="stn-table-columns-setting__columns-setting__item-content">
                          <div
                            :class="
                              column.draggable ?
                                'stn-table-columns-setting__columns-setting__item-handler' :
                                'stn-table-columns-setting__columns-setting__item-handler--disabled'
                            "
                          >
                            <slot name="drag-icon">
                              <st-icon-iconify :icon="ArrowsMoveVertical" width="16"/>
                            </slot>
                          </div>
                          <div class="stn-table-columns-setting__columns-setting__item-checkbox">
                            <n-checkbox size="small" :disabled="column.disableChecked" v-model:checked="column.checked">
                              <span style="white-space: nowrap">{{ column.title }}</span>
                            </n-checkbox>
                          </div>
                        </div>
                      </n-list-item>
                    </div>
                  </VueDraggable>
                </n-scrollbar>
              </n-list>
            </n-tab-pane>
            <n-tab-pane :name="colFixTabName">
              <n-list hoverable clickable>
                <n-list-item>
                  <div class="stn-table-columns-setting__columns-setting__all-reset">
                    <n-checkbox
                      size="small"
                      v-model:checked="isAllColumnsFixed"
                      :indeterminate="isIndeterminateColumnsFixed"
                      @update:checked="updateColumnsFixedAllHandler"
                    >
                      <span style="white-space: nowrap">{{ allText }}</span>
                    </n-checkbox>
                    <n-button text size="small" @click="resetColumnsFixedHandler">{{ resetText }}</n-button>
                  </div>
                </n-list-item>
                <n-scrollbar
                  class="stn-table-columns-setting__columns-setting__list"
                  :style="{maxHeight: elSizeUtil.elSizePreHandler(listMaxHeight)}"
                  trigger="none"
                >
                  <div
                    v-for="column in columns"
                    :key="column.title"
                    class="stn-table-columns-setting__columns-setting__item"
                  >
                    <n-list-item>
                      <div class="stn-table-columns-setting__columns-setting__item-content">
                        <div class="stn-table-columns-setting__columns-setting__item-checkbox">
                          <n-checkbox
                            size="small"
                            :disabled="!(column.originFixed)"
                            v-model:checked="column.fixed"
                            :checked-value="column.originFixed"
                            :unchecked-value="false"
                          >
                            <span style="white-space: nowrap">{{ column.title }}</span>
                          </n-checkbox>
                        </div>
                      </div>
                    </n-list-item>
                  </div>
                </n-scrollbar>
              </n-list>
            </n-tab-pane>
            <n-tab-pane :name="colAlignTabName">
              <n-list hoverable clickable>
                <n-list-item>
                  <div
                    class="stn-table-columns-setting__columns-setting__all-reset"
                    style="justify-content: flex-end"
                  >
                    <n-button text size="small" @click="resetColumnsAlignHandler">{{ resetText }}</n-button>
                  </div>
                </n-list-item>
                <n-scrollbar
                  class="stn-table-columns-setting__columns-setting__list"
                  :style="{maxHeight: elSizeUtil.elSizePreHandler(listMaxHeight)}"
                  trigger="none"
                >
                  <div
                    v-for="column in columns"
                    :key="column.title"
                    class="stn-table-columns-setting__columns-setting__item"
                  >
                    <n-list-item>
                      <div class="stn-table-columns-setting__columns-setting__item-align">
                        <div class="stn-table-columns-setting__columns-setting__item-align__title">
                          <span style="white-space: nowrap">{{ column.title }}</span>
                        </div>
                        <n-radio-group v-model:value="column.align" size="small">
                          <n-radio-button :value="'left'">{{ leftText }}</n-radio-button>
                          <n-radio-button :value="'center'">{{ centerText }}</n-radio-button>
                          <n-radio-button :value="'right'">{{ rightText }}</n-radio-button>
                        </n-radio-group>
                      </div>
                    </n-list-item>
                  </div>
                </n-scrollbar>
              </n-list>
            </n-tab-pane>
            <slot name="tab-extra" :columns="columns"></slot>
          </n-tabs>
        </div>
      </template>
    </StPopover>
  </div>
</template>

<style scoped lang="scss">
.stn-table-columns-setting {

  :deep(.n-list.n-list--bordered .n-list-item),
  :deep(.n-list.n-list--hoverable .n-list-item) {
    padding: 0;
  }

  .stn-table-columns-setting__columns-setting {
    padding: 0.5rem;
    border-radius: 0.5rem;
    overflow: hidden;

    .stn-table-columns-setting__columns-setting__all-reset {
      padding: 0.5rem;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .stn-table-columns-setting__columns-setting__list {
      overflow-y: auto;

      .stn-table-columns-setting__columns-setting__item {

        .stn-table-columns-setting__columns-setting__item-content {
          display: flex;
          align-items: center;

          .stn-table-columns-setting__columns-setting__item-handler {
            padding: 0.75rem 0 0.75rem 0.75rem;
            cursor: move;
          }

          .stn-table-columns-setting__columns-setting__item-handler--disabled {
            padding: 0.75rem 0 0.75rem 0.75rem;
            cursor: not-allowed;
            color: rgb(209, 213, 219);
          }

          .stn-table-columns-setting__columns-setting__item-handler,
          .stn-table-columns-setting__columns-setting__item-handler--disabled {
            display: flex;
            justify-content: center;
            align-items: center;
          }

          .stn-table-columns-setting__columns-setting__item-checkbox {
            flex: 1;
            padding: 0.6rem 0 0.6rem 0.6rem;
          }
        }

        .stn-table-columns-setting__columns-setting__item-align {
          padding: 0.5rem;

          .stn-table-columns-setting__columns-setting__item-align__title {
            margin-bottom: 0.25rem;
          }
        }
      }
    }
  }
}
</style>
